package com.wsdk.util;

import android.text.TextUtils;
import android.util.Log;

import com.wsdk.service.BluetoothLeService;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class ControlUtil {
    private static final String SERVER_DEFAULT_KEY = JniCoreBridge.fetchServerDefaultKey();
    private boolean isVersion2 = true;

    private byte flag = 0x10;
    private byte[] updateFileBlockSize;

    private byte[] sendLen01 = intToByteArray(132);
    private byte[] sendLen02 = intToByteArray(136);
    private byte[] sendLen03 = intToByteArray(8);

    private byte[] beforeCmd;

    private int packetNo = 1;
    private int fileLen;
    private int offset = 0;

    public int sumDataBlock = 0;
    private static final byte[] KEY = JniCoreBridge.fetchEncryptKey();
    private static byte[] NEW_KEY = new byte[8];

    public ControlUtil() {
    }

    public ControlUtil(boolean isVersion2) {
        this.isVersion2 = isVersion2;
    }


    /**
     * 设置序列号
     */
    public void setSN(String SN) {
        byte[] cmd = {0x03};
        byte[] sn = null;
        /*
         * 将字符串中的每一个字符转换为对应的ascii16进制字节码
         * 如110MS1710190005
         * 1 →  0x31
         * 整个序列号数据0x31 0x31 0x30 0x4d 0x53 0x31 0x37 0x31 0x30 0x31 0x39 0x30 0x30 0x30 0x35
         */
        try {
            sn = SN.getBytes("ASCII");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        List<Byte> packet = new ArrayList<>();
        for (int i = 0; i < 15; i++) {

            packet.add(sn[i]);
        }
        writeValue(cmd,packet);
    }


    /**
     * 获取KEY
     */
    public void fetchKey() {
        byte[] cmd = {0x15};
        writeValue(cmd);
    }

    /**
     * 初始化
     */
    public void init() {
        byte[] cmd = {0x01};
        writeValue(cmd);
    }

    /**
     * 新版初始化-第一步
     */
    public void init1(String mKey1, String mKey3, String sn) {
        desCheck(hexStr2Bytes(sn.substring(sn.length() - 16, sn.length())));
        LogUtil.e("NewKey:" + bytesToHexString(NEW_KEY));
        LogUtil.e("connectKeys:" + mKey1 + "-" + mKey3);
        LogUtil.e("connectKeysByte:" + bytesToHexString(mKey1.getBytes()) + "-" + bytesToHexString(
                mKey3.getBytes()));

        // 命令字
        byte[] cmd = {0x01};
        // 封装数据域
        List<Byte> packet = new ArrayList<>();
        // 初始化第一步标志位
        packet.add((byte) 0x01);

        /*
    	 * 将转换后得到的自己数组通过之前得到的新密钥进行des加密
    	 * 加密后得到16位的字节数组，取前八位，添加到数据域
    	 */
        try {
            byte[] m1 = mKey1.getBytes();
            byte[] m3 = mKey3.getBytes();
            if (TextUtils.equals(SERVER_DEFAULT_KEY, mKey1)) {
                m1 = KEY;
            }
            if (TextUtils.equals(SERVER_DEFAULT_KEY, mKey3)) {
                m3 = KEY;
            }
            byte[] desMK1 = DesUtil.encrypt(m1, NEW_KEY);
            byte[] desMK2 = DesUtil.encrypt(m3, NEW_KEY);
            for (int i = 0; i < 8; i++) {
                packet.add(desMK1[i]);
            }
            for (int i = 0; i < 8; i++) {
                packet.add(desMK2[i]);
            }
            LogUtil.e(
                    "connectEncryptKeysByte:" + bytesToHexString(desMK1) + "-" + bytesToHexString(desMK2));
            LogUtil.e("connectDecryptKeysByte:" + bytesToHexString(
                    DesUtil.decrypt(desMK1, NEW_KEY)) + "-" + bytesToHexString(
                    DesUtil.decrypt(desMK2, NEW_KEY)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将命令字与数据域进行打包发送（有数据域指令）
        writeValue(cmd, packet);
    }

    /**
     * 初始化第二步
     */
    public void init2(String mKey4, String mKey3, String wKey1, String wKey2, String sn) {
        desCheck(hexStr2Bytes(sn.substring(sn.length() - 16, sn.length())));

        // 命令字
        byte[] cmd = {0x01};
        // 封装数据域，此处原理与初始化第一步相同
        List<Byte> packet = new ArrayList<>();
        // 初始化第二部标志位
        packet.add((byte) 0x02);
        try {
            byte[] m4 = mKey4.getBytes();
            byte[] m3 = mKey3.getBytes();
            byte[] w1 = wKey1.getBytes();
            byte[] w2 = wKey2.getBytes();
            if (TextUtils.equals(SERVER_DEFAULT_KEY, mKey4)) {
                m4 = KEY;
            }
            if (TextUtils.equals(SERVER_DEFAULT_KEY, mKey3)) {
                m3 = KEY;
            }
            byte[] desMK4 = DesUtil.encrypt(m4, NEW_KEY);
            byte[] desMK3 = DesUtil.encrypt(m3, NEW_KEY);
            byte[] desWK1 = DesUtil.encrypt(w1, NEW_KEY);
            byte[] desWK2 = DesUtil.encrypt(w2, NEW_KEY);
            for (int i = 0; i < 8; i++) {
                packet.add(desMK4[i]);
            }
            for (int i = 0; i < 8; i++) {
                packet.add(desMK3[i]);
            }
            for (int i = 0; i < 8; i++) {
                packet.add(desWK1[i]);
            }
            for (int i = 0; i < 8; i++) {
                packet.add(desWK2[i]);
            }
            LogUtil.e("connectEncryptKeysByte:" + bytesToHexString(desMK4) + "-" + bytesToHexString(
                    desMK3));
            LogUtil.e("connectDecryptKeysByte:" + bytesToHexString(
                    DesUtil.decrypt(desMK4, NEW_KEY)) + "-" + bytesToHexString(
                    DesUtil.decrypt(desMK3, NEW_KEY)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        writeValue(cmd, packet);
    }

    /**
     * 换章
     */
    public void changeStamp() {
        byte[] cmd = {0x0C};
        List<Byte> packet = new ArrayList<>();
        packet.add((byte) 0x01);
        writeValue(cmd, packet);
    }

    /**
     * 取消换章
     */
    public void cancelChangeStamp() {
        byte[] cmd = {0x0C};
        List<Byte> packet = new ArrayList<>();
        packet.add((byte) 0x00);
        writeValue(cmd, packet);
    }

    /**
     * 开启老板
     */
    public void openBoss() {
        byte[] cmd = {0x0D};
        List<Byte> packet = new ArrayList<>();
        packet.add((byte) 0x00);
        writeValue(cmd, packet);
    }

    /**
     * 关闭老板
     */
    public void closeBoss() {
        byte[] cmd = {0x0D};
        List<Byte> packet = new ArrayList<>();
//        packet.add((byte) 0x07);
        packet.add((byte) 0x01);
        writeValue(cmd, packet);
    }

    /**
     * 维修模式
     */
    public void repairMode() {
        byte[] cmd = {0x0D};
        List<Byte> packet = new ArrayList<>();
        packet.add((byte) 0x02);
        writeValue(cmd, packet);
    }

    /**
     * 工作模式
     */
    public void workMode() {
        byte[] cmd = {0x0D};
        List<Byte> packet = new ArrayList<>();
        packet.add((byte) 0x03);
        writeValue(cmd, packet);
    }

    /**
     * 盖章开锁
     */
    public void stamp() {
        byte[] cmd = {0x07};
        List<Byte> packet = new ArrayList<>();
        packet.add((byte) 0x01);
        packet.add((byte) 0x00);
        writeValue(cmd, packet);
    }

    public void testPacket(String testString) {
        byte[] byteDate = hexStr2Bytes(testString);
        byte[] cmd = new byte[8];
        cmd[0] = 0x02;
        System.arraycopy(byteDate, 0, cmd, 1, 7);
        writeValue(cmd);
    }

    /**
     * 上锁
     */
    public void lock() {
        byte[] cmd = {0x08};
        writeValue(cmd);
    }

    /**
     * 获取序列号
     */
    public void getSN() {
        byte[] cmd = {0x04};
        LogUtil.e("getSn");
        writeValue(cmd);
    }

    /**
     * 总清（清除信印上所有数据）
     */
    public void clearAll() {
        byte[] cmd = {0x11};
        writeValue(cmd);
    }

    /**
     * 删除报警信息
     */
    public void deleteAlert() {
        byte[] cmd = {0x0f};
        writeValue(cmd);
    }

    /**
     * 获取版本号
     */
    public void checkVersion() {
        byte[] cmd = {0x02};
        LogUtil.e("checkVersion");
        writeValue(cmd);
    }

    /**
     * 同步时间
     */
    public void sycTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
        String date = simpleDateFormat.format(new Date(System.currentTimeMillis()));
        byte[] byteDate = hexStr2Bytes(date);
        byte[] cmd = new byte[8];
        cmd[0] = 0x0e;
        System.arraycopy(byteDate, 0, cmd, 1, 7);
        LogUtil.e("sycTime");
        writeValue(cmd);
    }

    public void sysServerTime(String time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
        String date = simpleDateFormat.format(new Date(Long.valueOf(time) + 5000));
        byte[] byteDate = hexStr2Bytes(date);
        byte[] cmd = new byte[8];
        cmd[0] = 0x0e;
        System.arraycopy(byteDate, 0, cmd, 1, 7);
        LogUtil.e("sycTime");
        writeValue(cmd);
    }

    /**
     * 身份验证（连接）
     */
    public void connect(String wKey2, String wKey3, String sn, String time) {
        desCheck(hexStr2Bytes(sn.substring(sn.length() - 16, sn.length())));

        LogUtil.e("connectTo:" + bytesToHexString(NEW_KEY));
        LogUtil.e("connectKeys:" + wKey2 + "-" + wKey3);
        LogUtil.e("connectKeysByte:" + bytesToHexString(wKey2.getBytes()) + "-" + bytesToHexString(
                wKey3.getBytes()));

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
        String date = simpleDateFormat.format(new Date(Long.valueOf(time) + 5000));
        byte[] byteDate = hexStr2Bytes(date);
        byte[] cmd = {0x0e};
        /*
         * 身份验证指令需要发送当前时间
         * 如20171019093026 转换成对应字节 0x20 0x17 0x10 0x19 0x09 0x30 0x26
         */
        List<Byte> packet = new ArrayList<>();
        for (int i = 1; i < 8; i++) {
            packet.add(byteDate[i - 1]);
        }

        try {
            // 此处添加的两个wkey从服务器获取，经des加密后发送给蓝牙,处理方法与初始化指令相同
            byte[] m1 = DesUtil.encrypt(wKey2.getBytes(), NEW_KEY);
            for (int i = 1; i <= 8; i++) {
                packet.add(m1[i - 1]);
            }
            byte[] m2 = DesUtil.encrypt(wKey3.getBytes(), NEW_KEY);
            for (int i = 1; i <= 8; i++) {
                packet.add(m2[i - 1]);
            }
            LogUtil.e(
                    "connectEncryptKeysByte:" + bytesToHexString(m1) + "-" + bytesToHexString(m2));
            LogUtil.e("connectDecryptKeysByte:" + bytesToHexString(
                    DesUtil.decrypt(m1, NEW_KEY)) + "-" + bytesToHexString(
                    DesUtil.decrypt(m2, NEW_KEY)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        writeValue(cmd, packet);
    }

    /**
     * 删除报警信息
     */
    public void deleteWarningInfo() {
        byte[] cmd = {0x0F};
        List<Byte> packet = new ArrayList<>();
        packet.add(cmd[0]);
        writeValue(packet);
    }

    private File tmpFile;
    private static int PACKET_SEND_INTERVAL = 30;

    /**
     * 升级固件
     */
    public void updateVersion(File file) {
        tmpFile = file;
        updateFileBlockSize = getFileBytes(file.getPath());

        fileLen = updateFileBlockSize.length;
        sumDataBlock = updateFileBlockSize.length / 128;

        LogUtil.e("----update1---" + sumDataBlock);

        if (updateFileBlockSize.length % 128 != 0) {
            sumDataBlock++;
        }
        byte[] cmd = new byte[130];
        cmd[0] = 0x1f;
        cmd[1] = 0x01;
        byte[] fileLen = int2bytes(updateFileBlockSize.length);

        //02 xx00 1f     01      [128]   0D   03
        //            升级命令字  数据域（8个字节，前4个字节是0，后四个字节是长度）
        System.arraycopy(fileLen, 0, cmd, 6, 4);
        writeValue(cmd);
    }

    /**
     * 发送文件序号为1的包
     *
     * @return packetNo
     */
    public int updateVersion2() {
        byte[] dd = new byte[133];
        dd[0] = 0x02;
        byte[] len = int2bytes(packetNo);
        System.arraycopy(len, 0, dd, 1, 4);
        if (fileLen > 128) {
            System.arraycopy(updateFileBlockSize, offset, dd, 5, 128);
            offset += 128;
            fileLen -= 128;
        } else {
            System.arraycopy(updateFileBlockSize, offset, dd, 5, fileLen);
            offset += fileLen;
            fileLen = 0;
        }

        beforeCmd = dd;

        List<byte[]> list;
        list = makePackets(makeUpdateDataPacket(dd));
        LogUtil.e("--------------------------------");
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) != null && bytesToHexString(list.get(i)) != null) {
                BluetoothLeService.writeValue(list.get(i));
                LogUtil.e("send2 " + bytesToHexString(list.get(i)));
            }
            try {
                Thread.sleep(PACKET_SEND_INTERVAL);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        LogUtil.e("--------------------------------");
        return packetNo;
    }

    /**
     * 错误或者无返回重传
     */
    public void retrainUpdate() {
        if (PACKET_SEND_INTERVAL < 120) {
            PACKET_SEND_INTERVAL += 30;
        }
        if (beforeCmd == null) {
            updateVersion(tmpFile);
        }
        List<byte[]> list;
        list = makePackets(makeUpdateDataPacket(beforeCmd));
        LogUtil.e("--------------------------------");
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) != null && bytesToHexString(list.get(i)) != null) {
                BluetoothLeService.writeValue(list.get(i));
                LogUtil.e("resend " + bytesToHexString(list.get(i)));
            }
            try {
                Thread.sleep(PACKET_SEND_INTERVAL);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        LogUtil.e("--------------------------------");
    }

    public int updateVersion3() {
        byte[] dd;
        if (fileLen == 0) {
            LogUtil.e("----update3---" + packetNo);
            dd = new byte[129];
            dd[0] = 0x03;
            byte[] fileLen = int2bytes(updateFileBlockSize.length);
            System.arraycopy(fileLen, 0, dd, 1, 4);

            int c = 0;
            for (byte updateFileBlock : updateFileBlockSize) {
                c += (updateFileBlock < 0 ? updateFileBlock + 256 : updateFileBlock);
            }
            byte[] check = int2bytes(c);

            LogUtil.e("---文件校验和------" + bytesToHexString(check));
            System.arraycopy(check, 0, dd, 5, 4);
            List<byte[]> list;
            list = makePackets(makeUpdateDataPacket03(dd));
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i) != null && bytesToHexString(list.get(i)) != null) {
                    BluetoothLeService.writeValue(list.get(i));
                    System.out.println("send3 " + bytesToHexString(list.get(i)));
                }
                try {
                    Thread.sleep(PACKET_SEND_INTERVAL);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } else {
            /*
              similar to update 2
             */
            packetNo++;
            dd = new byte[133];
            dd[0] = 0x02;
            byte[] len = int2bytes(packetNo);
            System.arraycopy(len, 0, dd, 1, 4);
            if (fileLen > 128) {
                System.arraycopy(updateFileBlockSize, offset, dd, 5, 128);
                offset += 128;
                fileLen -= 128;
            } else {
                System.arraycopy(updateFileBlockSize, offset, dd, 5, fileLen);
                offset += fileLen;
                fileLen = 0;
            }

            beforeCmd = dd;
            List<byte[]> list;
            list = makePackets(makeUpdateDataPacket(dd));
            LogUtil.e("--------------------------------");
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i) != null && bytesToHexString(list.get(i)) != null) {
                    BluetoothLeService.writeValue(list.get(i));
                    LogUtil.e("send32 " + bytesToHexString(list.get(i)));
                }
                try {
                    Thread.sleep(PACKET_SEND_INTERVAL);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            LogUtil.e("--------------------------------");
        }
        return packetNo;
    }

    private List<Byte> makeUpdateDataPacket(byte[] dd) {
        byte[] d = new byte[139];
        d[0] = 0x02;
        d[1] = sendLen02[1];
        d[2] = sendLen02[0];
        d[3] = 0x1f;
        System.arraycopy(dd, 0, d, 4, dd.length);

        int checkByte = 0;
        for (int i = 1; i < d.length; i++) {
            checkByte += d[i];
        }

        byte[] c = {(byte) checkByte, (byte) 0xAD, 0x61, (byte) 0xA5, (byte) 0xF7, 0x19, 0x77,
                0x14};
        byte[] checkDes = new byte[8];
        try {
            checkDes = DesUtil.encrypt(c, KEY);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (isVersion2) {
            d[137] = (byte) checkByte;
        } else {
            d[137] = checkDes[7];
        }
        d[138] = 0x03;

        LogUtil.e(bytesToHexString(d));

        List<Byte> packet = new ArrayList<>();
        for (byte aD : d) {
            packet.add(aD);
        }
        for (int i = 1; i < packet.size() - 1; i++) {
            if (packet.get(i) == 0x02 || packet.get(i) == 0x03 || packet.get(i) == 0x10) {
                packet.add(i, flag);
                ++i;
            }
        }
        return packet;
    }

    private List<Byte> makeUpdateDataPacket03(byte[] dd) {
        byte[] d = new byte[135];
        d[0] = 0x02;
        d[1] = (byte) 0x84;
        d[2] = 0x00;
        d[3] = 0x1f;
        System.arraycopy(dd, 0, d, 4, dd.length);

        int checkByte = 0;
        for (int i = 1; i < d.length; i++) {
            checkByte += d[i];
        }

        byte[] c = {(byte) checkByte, (byte) 0xAD, 0x61, (byte) 0xA5, (byte) 0xF7, 0x19, 0x77,
                0x14};
        byte[] checkDes = new byte[8];
        try {
            checkDes = DesUtil.encrypt(c, KEY);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (isVersion2) {
            d[133] = (byte) checkByte;
        } else {
            d[133] = checkDes[7];
        }
        d[134] = 0x03;
        List<Byte> packet = new ArrayList<>();
        for (byte aD : d) {
            packet.add(aD);
        }
        for (int i = 1; i < packet.size() - 1; i++) {
            if (packet.get(i) == 0x02 || packet.get(i) == 0x03 || packet.get(i) == 0x10) {
                packet.add(i, flag);
                ++i;
            }
        }
        return packet;
    }

    private List<byte[]> makePackets(List<Byte> list) {
        List<byte[]> packets = new ArrayList<>();
        int front = list.size() / 20;
        int last = list.size() % 20;
        for (int j = 0; j < front; j++) {
            byte[] packet = new byte[20];
            for (int i = 0; i < 20; i++) {
                packet[i] = list.get(0);
                list.remove(0);
            }
            packets.add(packet);
        }
        byte[] end = new byte[last];
        for (int i = 0; i < last; i++) {
            end[i] = list.get(i);
        }
        packets.add(end);
        return packets;
    }

    private byte[] getFileBytes(String pathStr) {
        InputStream is;
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try {
            is = new FileInputStream(pathStr);
            byte[] b = new byte[1024];
            int n;
            while ((n = is.read(b)) != -1) {
                out.write(b, 0, n);
            }
        } catch (Exception e) {
            Log.i("err", e.getMessage());
        }

        return out.toByteArray();
    }

    /**
     * 写数据 ，只需输入命令字的情况，无数据域
     *
     * @param cmd 命令字
     */
    private void writeValue(byte[] cmd) {
        writeValue(cmd, new ArrayList<Byte>());
    }

    /**
     * 写数据,packet已经确定的情况,
     *
     * @param packet 已经包含命令字与数据域
     */
    private void writeValue(List<Byte> packet) {
        writeValue(packet, new ArrayList<Byte>());
    }

    /**
     * 写数据，需要写入命令字与数据域
     *
     * @param cmd       命令字
     * @param extraData 数据域
     */
    private void writeValue(byte[] cmd, List<Byte> extraData) {
        List<Byte> packet = new ArrayList<>();
        for (byte aCmd : cmd) {
            packet.add(aCmd);
        }
        writeValue(packet, extraData);
    }

    /**
     * 写数据，packet中不包含数据域
     *
     * @param packet    packet
     * @param extraData 数据域
     */
    private void writeValue(List<Byte> packet, List<Byte> extraData) {
        //要发送的20字节数组
        List<byte[]> list = separate(makeDataPacket(packet, extraData));

        for (int i = 0; i < list.size(); i++) {
            LogUtil.e("Need Send Data：" + bytesToHexString(list.get(i)));
            BluetoothLeService.writeValue(list.get(i));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 有数据时，添加数据域
     */
    private List<Byte> makeDataPacket(List<Byte> packet, List<Byte> extraData) {
        //3代表 长度字两个字节+命令字一个字节，  size为数据域的长度
        byte[] length = intToByteArray(packet.size() + 2 + extraData.size());
        byte packetHead = 0x02;
        // 添加包头
        packet.add(0, packetHead);
        // 添加长度字低位
        packet.add(1, length[1]);
        // 添加长度字高位
        packet.add(2, length[0]);
        // packet[3] 为命令字
        /*
         * 数据域
         */
        for (int i = 0; i < extraData.size(); i++) {
            // 这里的数字要注意
            packet.add(i + 4, extraData.get(i));
        }

        // 检验字
        int checkByte = 0;
        for (int i = 1; i < packet.size(); i++) {
            checkByte += packet.get(i);
        }

        byte[] c = {(byte) checkByte, (byte) 0xAD, 0x61, (byte) 0xA5, (byte) 0xF7, 0x19, 0x77,
                0x14};
        byte[] checkDes = new byte[8];
        // 添加校验字
        if (isVersion2) {
            packet.add(packet.size(), (byte) checkByte);
        } else {
            try {
                checkDes = DesUtil.encrypt(c, KEY);
                LogUtil.e("Send Data Before Encrypt:" + bytesToHexString(c));
                LogUtil.e("Send Data After Encrypt:" + bytesToHexString(checkDes));
                byte[] result = DesUtil.decrypt(checkDes, KEY);
                LogUtil.e("Send Data After Decrypt:" + bytesToHexString(result));
            } catch (Exception e) {
                e.printStackTrace();
            }
            packet.add(packet.size(), checkDes[7]);
        }
        byte packetEnd = 0x03;
        // 添加包尾
        packet.add(packet.size(), packetEnd);
        // 校验字：从长度字到数据域最后一字节的逐字节累加值进行des加密后取低字节。
        // 除包头包尾外，遇0x02、0x03、0x10在其前加标志位0x10。
        for (int i = 1; i < packet.size() - 1; i++) {
            if (packet.get(i) == 0x02 || packet.get(i) == 0x03 || packet.get(i) == 0x10) {
                packet.add(i, flag);
                ++i;
            }
        }

        return packet;
    }

    /**
     * 将所有内容分割成20字节的数组
     */
    private List<byte[]> separate(List<Byte> list) {
        List<byte[]> packets = new ArrayList<>();
        int front = list.size() / 20;
        int last = list.size() % 20;
        for (int j = 0; j < front; j++) {
            byte[] packet = new byte[20];
            for (int i = 0; i < 20; i++) {
                packet[i] = list.get(0);
                list.remove(0);
            }
            packets.add(packet);
        }
        byte[] end = new byte[last];
        for (int i = 0; i < last; i++) {
            end[i] = list.get(i);
        }
        packets.add(end);
        return packets;
    }

    /**
     * 序列号后8位字节与KEY异或，生成新key
     * @param sn sn
     */
    private void desCheck(byte[] sn) {
        LogUtil.e("DesCheck Sn:" + bytesToHexString(sn));
        byte[] nk = new byte[8];
        for (int i = 0; i < 8; i++) {
            nk[i] = (byte) (sn[i] ^ KEY[i]);
        }
        NEW_KEY = nk;
    }

    /**
     * 长度字
     *
     * @param i 个数
     */
    private static byte[] intToByteArray(int i) {
        byte[] result = new byte[2];
        //由高位到低位
        result[0] = (byte) ((i >> 8) & 0xFF);
        result[1] = (byte) (i & 0xFF);
        return result;
    }

    private static byte[] int2bytes(int num) {
        byte[] result = new byte[4];
        result[3] = (byte) ((num >>> 24) & 0xff);
        result[2] = (byte) ((num >>> 16) & 0xff);
        result[1] = (byte) ((num >>> 8) & 0xff);
        result[0] = (byte) ((num) & 0xff);
        return result;
    }

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (byte aSrc : src) {
            int v = aSrc & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    private static byte[] hexStr2Bytes(String src) {
        int m, n;
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            m = i * 2 + 1;
            n = m + 1;
            ret[i] = Byte.decode("0x" + src.substring(i * 2, m) + src.substring(m, n));
        }
        return ret;
    }

    /**
     * 数字字符串转换为16进制字节("01"> 0x01)
     *
     * @param str str
     */
    private byte stringToHexInt(String str) {
        return (byte) Integer.parseInt(str, 16);
    }
}
